#pragma once
#include <vector>
#include <string>
#include <unordered_map>
#include "GlobalVariable.h"
#include <variant>
using namespace std;

// 符号种类：变量、常量、函数、参数
enum SymbolKind { VAR, CONST, FUNC, PARAM };

// 符号信息
class Symbol {
public:
    string name;       // 符号名
    SymbolKind kind;   // 种类
    string type;       // 类型（如 "int", "void"）
    bool isInitialized;// 是否已初始化（用于常量检查）
    double value;      // 值（仅对变量和常量有效）
    Value* alloc; // 分配指针（仅对局部变量有效）
    GlobalVariable* gv; // 全局变量指针（仅对全局变量有效）
    Function* ft; // 函数类型指针（仅对函数有效）
    BasicBlock* bb; // 基本块指针（仅对函数参数有效）
    // 可扩展其他属性（如函数参数列表）

    bool isGlobal() const {
        // 逻辑：如果 gv 指针非空则为全局变量
        return gv != nullptr;
    }

    // 判断是否是局部变量（可选）
    bool isLocal() const {
        // 逻辑：如果 alloc 指针非空则为局部变量
        return alloc != nullptr;
    }
};

// 作用域：一个作用域对应一个符号表
class Scope {
public:
    unordered_map<string, Symbol> symbols; // 当前作用域的符号表
    Scope* parent;                         // 父作用域指针

    Scope(Scope* p = nullptr) : parent(p) {}
    // 查找符号（从当前作用域向上）
    Symbol* lookup(const string& name);
    // 添加符号到当前作用域
    bool addSymbol(const string& name, SymbolKind kind, const string& type, double data, Value* alloc=nullptr, GlobalVariable* gv = nullptr, Function* ft = nullptr, BasicBlock* bb = nullptr);

};

// 符号表管理器
class SymbolTable {
private:
    vector<Scope*> scopes; // 作用域栈
public:

    // 构造函数：初始化全局作用域
    SymbolTable();
    // 进入新作用域
    void enterScope();
    // 退出当前作用域
    void exitScope();
    // 获取当前作用域
    Scope* currentScope();
    // 查找符号（从当前作用域向上）
    Symbol* lookup(const string& name);
    // 添加符号到当前作用域
    bool addSymbol(const string& name, SymbolKind kind, const string& type, double data, Value* alloc=nullptr, GlobalVariable* gv = nullptr, Function* ft = nullptr, BasicBlock* bb = nullptr);
    // 检查是否为全局变量
    bool isGlobalVariable(const string& name);

};